﻿using System;

namespace dk.Helper.Base.Core
{
    public class WorldDownloader : IWorldDownloader
    {
        private const string VILLAGE_FILENAME = "village.txt";
        private const string PLAYER_FILENAME = "player.txt";
        private const string ALLY_FILENAME = "ally.txt";

        private readonly IWorldFileDownloader allyDownloader;
        private readonly IWorldFileDownloader playerDownloader;
        private readonly IWorldFileDownloader villageDownloader;

        private int allyDownloadProgress;

        private bool isAllyDownloadFinished;
        private bool isPlayerDownloadFinished;
        private bool isVillageDownloadFinished;
        private int playerDownloadProgress;
        private int villageDownloadProgress;

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Object"/> class.
        /// </summary>
        public WorldDownloader(string worldName, string serverAddress)
        {
            villageDownloader = new WorldFileDownloader(worldName, serverAddress);
            playerDownloader = new WorldFileDownloader(worldName, serverAddress);
            allyDownloader = new WorldFileDownloader(worldName, serverAddress);

            villageDownloader.DownloadProgressChanged += VillageDownloader_DownloadProgressChanged;
            playerDownloader.DownloadProgressChanged += PlayerDownloader_DownloadProgressChanged;
            allyDownloader.DownloadProgressChanged += AllyDownloader_DownloadProgressChanged;

            villageDownloader.DownloadFinished += VillageDownloader_DownloadFinished;
            playerDownloader.DownloadFinished += PlayerDownloader_DownloadFinished;
            allyDownloader.DownloadFinished += AllyDownloader_DownloadFinished;
        }

        #region IWorldDownloader Members

        /// <summary>
        /// Downloads this instance.
        /// </summary>
        public void Download()
        {
            villageDownloader.DownloadFile(VILLAGE_FILENAME);
            playerDownloader.DownloadFile(PLAYER_FILENAME);
            allyDownloader.DownloadFile(ALLY_FILENAME);
        }

        /// <summary>
        /// Occurs when download progress is changed.
        /// </summary>
        public event ProgressEventHandler DownloadProgressChanged;

        /// <summary>
        /// Occurs when download is completed.
        /// </summary>
        public event EventHandler DownloadCompleted;

        #endregion

        /// <summary>
        /// Handles the DownloadProgressChanged event of the VillageDownloader control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="dk.Helper.Base.ProgressEventArgs"/> instance containing the event data.</param>
        private void VillageDownloader_DownloadProgressChanged(object sender, ProgressEventArgs e)
        {
            villageDownloadProgress = e.Percentage;
            OnDownloadProgressChanged(new ProgressEventArgs(GetProgressPercentage()));
        }

        /// <summary>
        /// Handles the DownloadProgressChanged event of the PlayerDownloader control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="dk.Helper.Base.ProgressEventArgs"/> instance containing the event data.</param>
        private void PlayerDownloader_DownloadProgressChanged(object sender, ProgressEventArgs e)
        {
            playerDownloadProgress = e.Percentage;
            OnDownloadProgressChanged(new ProgressEventArgs(GetProgressPercentage()));
        }

        /// <summary>
        /// Handles the DownloadProgressChanged event of the AllyDownloader control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="dk.Helper.Base.ProgressEventArgs"/> instance containing the event data.</param>
        private void AllyDownloader_DownloadProgressChanged(object sender, ProgressEventArgs e)
        {
            allyDownloadProgress = e.Percentage;
            OnDownloadProgressChanged(new ProgressEventArgs(GetProgressPercentage()));
        }

        /// <summary>
        /// Gets the progress percentage.
        /// </summary>
        /// <returns></returns>
        private int GetProgressPercentage()
        {
            return (villageDownloadProgress + playerDownloadProgress + allyDownloadProgress)/3;
        }

        /// <summary>
        /// Handles the DownloadFinished event of the VillageDownloader control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void VillageDownloader_DownloadFinished(object sender, EventArgs e)
        {
            isVillageDownloadFinished = true;
            CheckDownloadCompleted();
        }

        /// <summary>
        /// Handles the DownloadFinished event of the PlayerDownloader control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void PlayerDownloader_DownloadFinished(object sender, EventArgs e)
        {
            isPlayerDownloadFinished = true;
            CheckDownloadCompleted();
        }

        /// <summary>
        /// Handles the DownloadFinished event of the AllyDownloader control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void AllyDownloader_DownloadFinished(object sender, EventArgs e)
        {
            isAllyDownloadFinished = true;
            CheckDownloadCompleted();
        }

        /// <summary>
        /// Determines whether download is completed.
        /// </summary>
        private void CheckDownloadCompleted()
        {
            if (isVillageDownloadFinished && isPlayerDownloadFinished && isAllyDownloadFinished)
            {
                OnDownloadCompleted(new EventArgs());
            }
        }

        /// <summary>
        /// Raises the DownloadProgressChanged event.
        /// </summary>
        /// <param name="e">The <see cref="dk.Helper.Base.ProgressEventArgs"/> instance containing the event data.</param>
        private void OnDownloadProgressChanged(ProgressEventArgs e)
        {
            if (DownloadProgressChanged != null) DownloadProgressChanged(this, e);
        }

        /// <summary>
        /// Raises the DownloadCompleted event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void OnDownloadCompleted(EventArgs e)
        {
            if (DownloadCompleted != null) DownloadCompleted(this, e);
        }
    }
}